package com.echat.elocation.protocol.code;

import com.echat.elocation.constant.ProtocolConstant;
import com.echat.elocation.protocol.entity.send.HeartbeatMsg;
import com.echat.elocation.protocol.entity.send.LocationUpLoadMsg;
import com.echat.elocation.protocol.entity.send.TerminalAuthenticationMsg;
import com.echat.elocation.protocol.entity.send.TerminalRegisterMsg;
import com.echat.elocation.util.BcdOperation;
import com.echat.elocation.util.BitOperation;
import com.echat.elocation.util.HexStringUtils;
import com.echat.elocation.util.ProtocolUtils;

import java.util.Arrays;

/**
 *
 * 消息编码
 *
 * @author lihao
 *
 * @date 2018/7/16 16:25
 */
public class MsgEncoder {

    /**
     * 注册消息
     *
     * @param msg 注册消息体
     * @return
     * @throws Exception
     */
    public byte[] encodeTerminalRegisterMsg(TerminalRegisterMsg msg) throws Exception {
        // 消息体
        byte[] body = BitOperation.concatAll(Arrays.asList(
                BitOperation.integerTo2Bytes(msg.getProvinceId()),
                BitOperation.integerTo2Bytes(msg.getCityId()),
                HexStringUtils.hexString2Bytes(HexStringUtils.preFillZero(msg.getManufacturerId(), 10)),
                HexStringUtils.hexString2Bytes(HexStringUtils.sufFillZero(msg.getTerminalType(), 40)),
//                HexStringUtils.hexToBytes(HexStringUtils.sufFillZero(msg.getTerminalId(), 14)),
                HexStringUtils.sufFillZero(msg.getTerminalId(), 7).getBytes(),
                BitOperation.integerTo1Bytes(msg.getLicensePlateColor()),
                msg.getLicensePlate().getBytes(ProtocolConstant.string_encoding)
        ));

        // 消息头
        int msgBodyProps = ProtocolUtils.generateMsgBodyProps(body.length);
        msg.getMsgHeader().setMsgBodyProps(msgBodyProps);
        byte[] header = ProtocolUtils.generateMsgHeader(msg.getMsgHeader());

        byte[] headerAndBody = BitOperation.concatAll(header, body);

        // 检验码
        int checkCode = ProtocolUtils.getCheckCode(headerAndBody);

        return doEncode(headerAndBody, checkCode);
    }

    /**
     * 鉴权消息
     *
     * @param msg 鉴权消息体
     * @return
     * @throws Exception
     */
    public byte[] encodeTerminalAuthMsg(TerminalAuthenticationMsg msg) throws Exception {
        // 消息体
        byte[] body = msg.getAuthCode().getBytes(ProtocolConstant.string_encoding);
        // 消息头
        int msgBodyProps = ProtocolUtils.generateMsgBodyProps(body.length);
        msg.getMsgHeader().setMsgBodyProps(msgBodyProps);
        byte[] header = ProtocolUtils.generateMsgHeader(msg.getMsgHeader());

        byte[] headerAndBody = BitOperation.concatAll(header, body);
        // 检验码
        int checkCode = ProtocolUtils.getCheckCode(headerAndBody);

        return doEncode(headerAndBody, checkCode);
    }

    /**
     * 心跳消息
     *
     * @param msg 消息体（null）
     * @return
     * @throws Exception
     */
    public byte[] encodeHeartbeatMsg(HeartbeatMsg msg) throws Exception {
        // 消息头
        int msgBodyProps = ProtocolUtils.generateMsgBodyProps(0);
        msg.getMsgHeader().setMsgBodyProps(msgBodyProps);
        byte[] header = ProtocolUtils.generateMsgHeader(msg.getMsgHeader());
        // 检验码
        int checkCode = ProtocolUtils.getCheckCode(header);
        return doEncode(header, checkCode);
    }

    /**
     * 位置上报消息
     *
     * @param msg 位置消息体
     * @return
     * @throws Exception
     */
    public byte[] encodeLocationUploadMsg(LocationUpLoadMsg msg) throws Exception {
        byte[] body = BitOperation.concatAll(Arrays.asList(
                BitOperation.integerTo4Bytes(msg.getWarningFlagField()),
                BitOperation.integerTo4Bytes(msg.getStatusField()),
                BitOperation.integerTo4Bytes((int) msg.getLatitude()),
                BitOperation.integerTo4Bytes((int) msg.getLongitude()),
                BitOperation.integerTo2Bytes(msg.getElevation()),
                BitOperation.integerTo2Bytes((int) msg.getSpeed()),
                BitOperation.integerTo2Bytes((int) msg.getDirection()),
                BcdOperation.string2Bcd(msg.getTime()),
                BitOperation.integerTo1Bytes(msg.getAppendMsgId()),
                BitOperation.integerTo1Bytes(msg.getAppendMsgLength()),
                BitOperation.integerTo4Bytes(msg.getAppendMsg())
        ));

        // 消息头
        int msgBodyProps = ProtocolUtils.generateMsgBodyProps(body.length);
        msg.getMsgHeader().setMsgBodyProps(msgBodyProps);
        byte[] header = ProtocolUtils.generateMsgHeader(msg.getMsgHeader());

        byte[] headerAndBody = BitOperation.concatAll(header, body);

        // 检验码
        int checkCode = ProtocolUtils.getCheckCode(headerAndBody);
        return doEncode(headerAndBody, checkCode);
    }


    private byte[] doEncode(byte[] headerAndBody, int checkCode) throws Exception {

        byte[] noEscapedBytes = BitOperation.concatAll(Arrays.asList(
                BitOperation.integerTo1Bytes(ProtocolConstant.pkg_delimiter),
                headerAndBody,
                BitOperation.integerTo1Bytes(checkCode),
                BitOperation.integerTo1Bytes(ProtocolConstant.pkg_delimiter)
        ));
        // 转义
        return ProtocolUtils.doEscape4Send(noEscapedBytes, 1, noEscapedBytes.length - 1);
    }
}
